package com.hsogoo.ultraman.container;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.hsogoo.ultraman.ConfigFactory;
import com.hsogoo.ultraman.ConfigFactoryRegistry;
import com.hsogoo.ultraman.exceptions.UltramanConfigException;
import com.hsogoo.ultraman.listener.RemoteConfigChangeListener;
import com.hsogoo.ultraman.monitor.ConfigChangeMonitor;
import com.hsogoo.ultraman.spring.refreshable.PlaceholderHelper;
import com.hsogoo.ultraman.spring.refreshable.RefreshableConfigRegistry;
import com.hsogoo.ultraman.utils.ConfigMetaUtil;
import com.hsogoo.ultraman.utils.HttpUtil;
import com.hsogoo.ultraman.spi.ConfigServerLocator;
import com.hsogoo.ultraman.spi.DefaultConfigFactory;
import com.hsogoo.ultraman.spi.DefaultConfigFactoryRegistry;

import lombok.extern.slf4j.Slf4j;

/**
 * Created by za-huangsaigang on 2018/9/20.
 */
@Slf4j
public class GuiceContainer implements Container {

    private Injector injector;

    public GuiceContainer(){
        try {
            injector = Guice.createInjector(new ConfigModule());
        } catch (Throwable ex) {
            UltramanConfigException exception = new UltramanConfigException("Unable to initialize Guice Injector!", ex);
            throw exception;
        }
    }

    @Override
    public <T> T getBean(Class<T> clazz) {
        try {
            return injector.getInstance(clazz);
        } catch (Throwable ex) {
            throw new UltramanConfigException(String.format("Unable to load instance for %s!", clazz.getName()), ex);
        }
    }

    private static class ConfigModule extends AbstractModule {
        @Override
        protected void configure() {
            bind(ConfigFactory.class).to(DefaultConfigFactory.class).in(Singleton.class);
            bind(ConfigFactoryRegistry.class).to(DefaultConfigFactoryRegistry.class).in(Singleton.class);
            bind(ConfigServerLocator.class).in(Singleton.class);
            bind(ConfigChangeMonitor.class).in(Singleton.class);
            bind(HttpUtil.class).in(Singleton.class);
            bind(ConfigMetaUtil.class).in(Singleton.class);
            bind(RefreshableConfigRegistry.class).in(Singleton.class);
            bind(PlaceholderHelper.class).in(Singleton.class);

        }
    }

}
